事务控制的3种方式
编程式事务:直接在代码里手动开启事务,手动提交,手动回滚。优点就是可以灵活控制,缺点就是太麻烦了,太多重复的代码了。声明式事务:就是使用Spring Aop配置事务,这种方式简化了编码。需要注意的是切入点表达式一定要写正确。注解事务:直接在Service层的方法上面加上@Transactional注解,最简单方便的方式。
伪代码
排序往后的方法报错,导致排序前的方法不回滚,如下:updataFlag方法出错,analyseRedBall 和 analyseBlueBall 方法不会回滚
public void statistics() {  | 
为什么不会滚呢
Spring默认情况下是捕获到方法的RuntimeException异常,也就是说只要属于RuntimeException异常或及其子类都能回滚。不属于运行时异常时,事务不回滚的。
解决方案
声明式事务
确保切入点表达式书写正确,如在配置里面添加rollback-for
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>  | 
注解事务
使用位置
类上:该类的所有public 方法将都具有务属性方法上:只能应用到 public 方法上,这是由Spring AOP的本质决定的,如果在protected、private或者默认可见性的方法上使用 @Transactional 注解,将被忽略,也不会抛出任何异常。接口、接口方法上:接口实现类或接口实现方法可继承事务属性,Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效
基本用法
将Spring默认的RuntimeException异常修改为Exception异常,可以保证任何异常都可以回滚。
或指定多个异常
如上述实例修改为
  | 
异常抛出
在catch语句中抛出异常,以便让Aop捕获异常执行回滚事务,如下伪代码
  | 
手动事务
配合事务注解@Transactional,手动处理事务回滚
设置回滚代码
在catch语句中设置回滚代码来实现回滚,此方法在抛出异常后也能return 返回值,适合需要拿到返回值的场景
  | 
设置回滚点
// 方法返回的是object类型,o 为回滚点变量名  | 
存储引擎
到此之前,代码无误,那为什么 Spring 或 SpringBoot 的事务回滚还是没有任何效果呢?
数据库肯定是
MySQL,那表的存储引擎,也要支持事务安全才行,最重要,也是最多人忽视的地方;InnoDB 和 BDB 提供事务安全表,其他存储引擎都是非事务安全表

注:
Oracleb不存在存储引擎的概念,数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。
- OLTP是
 传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。强调数据库内存效率,强调内存各种指标的命令率,强调绑定变量,强调并发操作- OLAP是
 数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。强调数据分析,强调SQL执行市场,强调磁盘I/O,强调分区等
总结
@Transactional和@Transactional(rollbackFor = Exception.class)的区别
@Transactional只能回滚RuntimeException和RuntimeException的子类抛出的异常,不能回滚Exception异常- 如果需要支持回滚
 Exception异常请用@Transactional(rollbackFor = Exception.class)增删改建议使用@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class)的失效场景
- 不是
 public修饰try...catch...捕获了异常(没在catch里面手动抛出异常)- 没有加
 @Service(没被 Spring 管理)
